#include <bits/stdc++.h>

#define in read()
#define fi first
#define se second
#define pb push_back
#define rep(i, x, y) for(int i = (x); i <= (y); i++) 
#define per(i, x, y) for(int i = (x); i >= (y); i--)

using namespace std;

using ll = long long;
using db = double;
using pii = pair < int , int >;
using vec = vector < int >;
using veg = vector < pii >;

int read() {
	int x = 0; bool f = 0; char ch = getchar(); while(!isdigit(ch)) f |= ch == '-', ch = getchar(); 
	while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar(); return f ? -x : x;
}

const int N = 3010;
const int mod = 1e9 + 7;

int C[N][N], H, W;
int f[N][N];

inline int upd(const int &x) { return x + (x >> 31 & mod); }

int main() {
#ifndef ONLINE_JUDGE
	freopen("1.in", "r", stdin);
#endif
	H = in, W = in; int l = max(H, W);
	rep(i, 0, l) C[i][0] = 1;
	rep(i, 1, l) {
		rep(j, 1, i) C[i][j] = upd(C[i - 1][j - 1] + C[i - 1][j] - mod);
	}
	f[0][0] = 1;
	rep(i, 1, H) {
		rep(j, 1, W) {
			if(j >= 1) f[i][j] = upd(f[i][j] + 1ll * f[i - 1][j - 1] * j % mod * 4 % mod - mod);
			if(j >= 2) f[i][j] = upd(f[i][j] + 1ll * f[i - 1][j - 2] * C[j][2] % mod - mod);
			if(i >= 2) f[i][j] = upd(f[i][j] + 1ll * f[i - 2][j - 1] * (i - 1) % mod * j % mod - mod);
		}
	}
	int ans = 0;
	rep(i, 1, H) 
		rep(j, 0, W) if(f[i][j]) {
		ans = upd(ans + 1ll * f[i][j] * C[H][i] % mod * C[W][j] % mod - mod);
	} printf("%d\n", ans);
	return 0;
}
